﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using WooCoo.Data;
using WooCoo.ObjectModel.Validation;

namespace WooCoo.ObjectModel
{
    public abstract partial class Entity
    {
        private static readonly MethodInfo updateMethodInfo = (MethodInfo)typeof(DataPortal.DataPortalClient).GetMember("Update").Single((MemberInfo m) => ((MethodInfo)m).GetGenericArguments().Count<Type>() == 1);
        #region DataPortal Method
        /// <summary>
        /// DataPortal端创建对象方法，等同为Create
        /// </summary>
        /// <param name="criteria"></param>
        protected virtual void DataPortal_Create(object criteria)
        {
            this.DataPortal_Update();
        }

        /// <summary>
        /// DataPortal端数据获取方法，可等同为Get
        /// </summary>
        /// <param name="criteria"></param>
        protected virtual void DataPortal_Fetch(object criteria)
        {
            //var cri = criteria as Criteria;
            //var query = from abc in this.GetRepository().AsQueryable()
            //            select abc.
            //if (this.GetRepository().GetEntity(this, cri) != null)
            //    this.MarkOld();
        }
        /// <summary>
        /// DataPortal端数据更新方法
        /// </summary>
        protected virtual void DataPortal_Update()
        {
            IUnitOfWork rep = this.GetRepository() as IUnitOfWork;
            using (var trm = rep.TransactionManager)
            {
                if (this.IsSelfDirty)
                    this.GetRepository().SaveChanges(this);
                this.UpdateChildren();
                trm.Commit();
            }
        }
        /// <summary>
        /// DataPortal端删除方法，可等同为Delete
        /// </summary>
        /// <param name="criteria"></param>
        protected virtual void DataPortal_Delete(object criteria)
        {
            //var item = this.GetRepository().AsQueryable().
            this.MarkDeleted();
            IUnitOfWork rep = this.GetRepository() as IUnitOfWork;
            using (var trm = rep.TransactionManager)
            {
                this.GetRepository().SaveChanges(this);
                trm.Commit();
            }
            //DataPortal_Update();
            //this.GetRepository().Remove(this);
            //IRepository rep = this.GetRepository();
            //using (TransactionManager trm = TransactionManager.GetManager(rep.Db.DbSetting, true))
            //{
            //    this.GetRepository().SaveChanges(this);
            //}
        }

        /// <summary>
        /// 调用数据门户提交所有子对象的更新。      
        /// </summary>
        /// <remarks>
        /// 该方法在服务端调用，以简化子对象在DataPortal.Update更新时的对象回传问题。
        /// </remarks>
        protected virtual void UpdateChildren()
        {
            foreach (var item in this.FieldDataManager.GetDirtyFieldDatas())
            {
                if (item != null && item is IEntityList)
                {
                    object obj = item.Value;
                    if (obj is Entity)
                    {
                        //Wcdf.DataPortal.UpdateChild(obj, parameters);
                        (obj as Entity).GetRepository().SaveChanges(obj);
                    }
                    else if (obj is System.Collections.IEnumerable)
                    {
                        var objList = obj as System.Collections.IEnumerable;
                        foreach (var eitem in objList)
                        {
                            if ((eitem as ITrackStatus).IsDirty)
                                (eitem as Entity).GetRepository().SaveChanges(eitem);
                        }
                    }
                }
            }
        }

        public void Save(bool force = false)
        {
            this.Save(DataPortal.DataPortalClient.Default, force);
        }

        /// <summary>
        /// 数据保存方法，更新到数据库操作用该方法。
        /// </summary>
        public void Save(DataPortal.DataPortalClient client, bool force = false)
        {
            if (this.Parent != null & !force)
            {
                //子对象不可单独更新
                throw new NotSupportedException(Localizer.Active.GetLocalizeString(StringID.NoSaveChildException));
            }
            else if (!IsValid && !this.IsDeleted)
            {
                //删除对象时，不做验证
                //该提示并不包含子对象的规则信息。
                string msg = string.Format(Localizer.Active.GetLocalizeString(StringID.NoSaveInvalidException)
                    + System.Environment.NewLine,
                    this.ValidationRules.BrokenRules.ToString());
                throw new ValidationException(msg);
            }
            else if (IsDirty)
            {
                updateMethodInfo.MakeGenericMethod(this.GetType()).Invoke(client, new object[] { this });
                //client.Update<object>(this);
                //保存成功后清除脏数据.
                this.MarkOld();
            }

        }

        #endregion
    }
}
